package com.keshi.openplatform.gateway.filters;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.discovery.converters.Auto;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.keshi.openplatform.commons.beans.BaseResultBean;
import com.keshi.openplatform.commons.constans.ExceptionDict;
import com.keshi.openplatform.commons.constans.SystemParams;
import com.keshi.openplatform.gateway.feign.CacheService;
import com.keshi.openplatform.gateway.utils.Md5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;


/**
 * 当前的过滤器主要作用是用于校验用户的请求中的签名是否正确,来判断是否是合法的请求
 */

@Component
public class SignFilter extends ZuulFilter {
    @Autowired
    private CacheService cacheService;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 30;
    }

    @Override
    public boolean shouldFilter() {
        return RequestContext.getCurrentContext().sendZuulResponse();
    }

    @Override
    public Object run() throws ZuulException {
        /**
         * 首先回顾下我们的规则, 我们的规则是将用户传递的参数中除了签名之外的数据 按照key的字典顺序进行排序,然后将排序后数据按照keyvaluekeyvalue的方式进行拼接字符串
         * 然后再获取用户的签名的秘钥,进行拼接,得到一个新的字符串,然后计算md5值,将计算的结果和用户传递的数据进行比较,一直则放行
         * 我们需要的数据就是用户传递的参数, 用户的app的秘钥,用户传递的签名
         */
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        Enumeration<String> parameterNames = request.getParameterNames();//获取所有的参数的名字
        Map<String, String> signMap = new HashMap<>();//用于保存除了签名之前的数据
        while (parameterNames.hasMoreElements()) {
            String name = parameterNames.nextElement();//获取每一个参数的名字
            if (!"sign".equalsIgnoreCase(name)) {
                signMap.put(name, request.getParameter(name));//保存除了sign之外的数据
            }
        }
        //我们现在要获取appsecret
        String app_key = request.getParameter("app_key");//获取应用的app key
        try {
//            Map<Object, Object> appInfoMap = cacheService.hGetAll(SystemParams.APPKEY_REDIS_PRE + app_key);
//            if (appInfoMap != null) {
//                Object appSecret = appInfoMap.get("appSecret");
//            }
            String appSecret = cacheService.hGet(SystemParams.APPKEY_REDIS_PRE + app_key, "appSecret");

            String md5Signature = Md5Util.md5Signature(signMap, appSecret);//计算用户传递的参数应该得到的签名

            String sign = request.getParameter("sign");//用户传递的签名

            System.err.println("系统计算的签名:" + md5Signature);
            System.err.println("用户传递的签名:" + sign);

            if (md5Signature.equalsIgnoreCase(sign)) {
                return null;//校验通过
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        //不管发生什么情况导致的校验失败,最终都会来这里执行代码

        context.setSendZuulResponse(false);
        HttpServletResponse response = context.getResponse();
        response.setContentType("appliaction/json;charset=utf-8");
        BaseResultBean bean = new BaseResultBean();
        bean.setCode(ExceptionDict.SYSTEMPARAM_SIGN_ERROR);
        bean.setMsg("签名校验失败");
        try {
            context.setResponseBody(objectMapper.writeValueAsString(bean));
        } catch (JsonProcessingException ex) {
            ex.printStackTrace();
        }

        return null;
    }
}
